#pragma once

#include <iostream>
#include <functional>
#include <string>
#include <pthread.h>
#include "Sock.hpp"
#include "Err.hpp"
#include "Log.hpp"
#include "Thread.hpp"

namespace ns_httpserver
{
    class HttpServer;

    class ThreadData
    {
    public:
        ThreadData()
        {}

        ThreadData(const int &sock, const std::string &ip, const uint16_t &port, HttpServer *ptsvr)
            :sock_(sock), ip_(ip), port_(port), ptsvr_(ptsvr)
        {
            logMessage(Info, "ThreadData Success sock_:%d ip_:%s port_%d ptsvr_:%p", sock_, ip_.c_str(), port_, ptsvr_);
        }

        ~ThreadData()
        {}

        int sock_;
        std::string ip_;
        uint16_t port_;
        HttpServer *ptsvr_;  //指向客户端对象的指针
    };

    using func_t = function<std::string(const std::string&)>;

    enum 
    {
        READ_FAIL = -1,
        READ_DONE,
        READ_SUCCESS
    };

    class HttpServer
    {
    public:
        HttpServer(const func_t &func, const uint16_t &port)
            :func_(func), port_(port)
        {
            logMessage(Info, "HttpServer Success func_:%p port_:%d", &func_, port);
        }

        ~HttpServer()
        {
            listen_sock_.Close();
        }

        void InitServer()
        {
            //初始化服务器：创建、绑定、监听
            listen_sock_.Socket();
            listen_sock_.Bind(port_);
            listen_sock_.Listen();

            //创建套接字成功之后，修改套接字的属性，让其复用老的端口号
            int opt = 1;
            setsockopt(listen_sock_.getFd(), SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
            logMessage(Info, "InitServer Success");
        }

        void StartServer()
        {
            while(true)
            {   
                sleep(1); 
                //观察全连接队列
            }

            // int num = 0;
            // //尝试链接客户端，链接成功后，创建次线程，执行回调方法
            // while(true)
            // {
            //     std::string clientip;
            //     uint16_t clientport;

            //     int sock = listen_sock_.Accept(&clientip, &clientport);
            //     if(sock == -1) continue;;

            //     //成功建立了链接
            //     //创建次线程，执行任务
            //     ThreadData *pt = new ThreadData(sock, clientip, clientport, this);
            //     Thread t(num++, threadRoutine, pt);
            // }
        }

        static void *threadRoutine(void *args)
        {
            logMessage(Info, "Thread %d Run", pthread_self());
            clock_t begin = clock();

            //获取线程信息类的指针
            ThreadData *pt = static_cast<ThreadData*> (args);

            //回调业务执行函数
            pt->ptsvr_->HttpRequestHandler(pt->sock_);

            delete pt;
            pt = nullptr;

            clock_t end = clock();
            logMessage(Info, "Thread %d Done (Time: %d)", pthread_self(), end - begin);
        }

        void HttpRequestHandler(int sock)
        {
            //读取数据（此时假设我们一次就把所有数据读完了）
            char buff[1024];

            std::string request;    //请求
            ssize_t n = recv(sock, buff, sizeof(buff) - 1, 0);

            if(n >= READ_SUCCESS)
            {
                buff[n] = 0;

                // logMessage(Info, "Read Success: %s", buff);

                request = buff;
                std::string respond = func_(request);  //获取回应（实际业务处理）

                //将消息回响给客户端
                send(sock, respond.c_str(), respond.size(), 0);
            }
            else if(n == READ_DONE)
            {
                logMessage(Debug, "Client Quit: %s", strerror(errno));
            }
            else
            {
                logMessage(Error, "Read Faile: %s", strerror(errno));
            }
        }

    private:
        func_t func_;   //回调方法（实际业务执行函数）
        Yohifo::Sock listen_sock_;   //监听套接字
        uint16_t port_; //端口号
    };
}